package com.oauth.google.server.youtube.service;

import java.net.URL;
import java.util.List;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;

import com.google.gdata.client.authn.oauth.GoogleOAuthHelper;
import com.google.gdata.client.authn.oauth.GoogleOAuthParameters;
import com.google.gdata.client.authn.oauth.OAuthHmacSha1Signer;
import com.google.gdata.client.authn.oauth.OAuthSigner;
import com.google.gdata.client.youtube.YouTubeService;
import com.google.gdata.data.media.MediaFeed;
import com.google.gdata.data.youtube.VideoEntry;
import com.google.gdata.data.youtube.VideoFeed;
import com.oauth.common.server.beans.OAuthAccessToken;
import com.oauth.common.server.beans.OAuthConfigBean;
import com.oauth.common.server.beans.OAuthRequestToken;
import com.oauth.google.client.beans.youtube.YouTubeVideo;
import com.oauth.google.server.beans.GoogleRequestToken;
import com.oauth.google.server.beans.GoogleYouTubeBean;
import com.oauth.google.server.constants.GoogleServiceType;
import com.oauth.google.server.youtube.util.GoogleYoutubeUtil;
import com.oauth.service.generic.OAuthService;
import com.oauth.service.generic.beans.OAuthServiceBean;

public class YoutubeOAuthServiceImpl implements YoutubeOAuthService {

	private GoogleOAuthHelper mOAuthHelper;
	private OAuthSigner mSigner;
	private OAuthService mOAuthService;
	private OAuthConfigBean mOAuthConfigBean;

	@PostConstruct
	public void initialise() {
		mSigner = new OAuthHmacSha1Signer();
		mOAuthHelper = new GoogleOAuthHelper(mSigner);
	}

	/**
	 * @param pOAuthService
	 *            the oAuthService to set
	 */
	@Autowired(required = true)
	public void setOAuthService(OAuthService pOAuthService) {
		mOAuthService = pOAuthService;
	}

	/**
	 * @param pOAuthConfigBean
	 *            the oAuthConfigBean to set
	 */
	@Required
	public void setOAuthConfigBean(OAuthConfigBean pOAuthConfigBean) {
		mOAuthConfigBean = pOAuthConfigBean;
	}

	private GoogleOAuthParameters getOAuthParameters() {
		GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
		oauthParameters.setOAuthConsumerKey(mOAuthConfigBean.getConsumerKey());
		oauthParameters.setOAuthConsumerSecret(mOAuthConfigBean
				.getConsumerSecret());
		oauthParameters.setScope(GoogleServiceType.YouTube.getScope());
		return oauthParameters;
	}

	private YouTubeService getYoutubeService(Long pMemberId) throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		OAuthAccessToken accessToken = getAccessTokenFromDB(pMemberId);
		oauthParameters.setOAuthToken(accessToken.getToken());
		oauthParameters.setOAuthTokenSecret(accessToken.getTokenSecret());

		YouTubeService youtubeService = new YouTubeService(
				GoogleServiceType.YouTube.getGoogleServiceName());
		// Set the OAuth credentials which were obtained from the step
		youtubeService.setOAuthCredentials(oauthParameters, mSigner);
		return youtubeService;
	}

	private <F extends MediaFeed<F, VideoEntry>> F getFeed(
			YouTubeService pYoutubeService, Class<F> pClass) throws Exception {
		URL feedUrl = new URL(GoogleServiceType.YouTube.getFeedUrl());
		return pYoutubeService.getFeed(feedUrl, pClass);
	}

	@Override
	public OAuthAccessToken getAccessTokenFromDB(Long pMemberId)
			throws Exception {
		OAuthServiceBean token = null;
		token = mOAuthService.getToken(pMemberId, GoogleYouTubeBean.class);
		if (token != null) {
			return new OAuthAccessToken(token.getAccessToken(), token
					.getAccessTokenSecret());
		}
		return null;
	}

	@Override
	public OAuthAccessToken getAccessTokenFromRequestToken(
			OAuthRequestToken pRequestToken, String pQueryString)
			throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		mOAuthHelper.getOAuthParametersFromCallback(pQueryString,
				oauthParameters);
		oauthParameters.setOAuthToken(pRequestToken.getToken());
		oauthParameters.setOAuthTokenSecret(pRequestToken.getTokenSecret());
		// Get access token .
		String accessToken = mOAuthHelper.getAccessToken(oauthParameters);
		return new OAuthAccessToken(accessToken, oauthParameters
				.getOAuthTokenSecret());
	}

	@Override
	public GoogleRequestToken getRequestToken() throws Exception {
		GoogleOAuthParameters oauthParameters = getOAuthParameters();
		mOAuthHelper.getUnauthorizedRequestToken(oauthParameters);
		oauthParameters.setOAuthCallback(mOAuthConfigBean.getCallBackUrl());
		String authorizeUrl = mOAuthHelper
				.createUserAuthorizationUrl(oauthParameters);
		GoogleRequestToken oauthTokenBean = new GoogleRequestToken(
				oauthParameters.getOAuthToken(), oauthParameters
						.getOAuthTokenSecret(), authorizeUrl);
		return oauthTokenBean;
	}

	@Override
	public void persistAccessToken(OAuthAccessToken pAccessToken, Long pMemberId)
			throws Exception {
		GoogleYouTubeBean serviceBean = new GoogleYouTubeBean();
		serviceBean.setAccessToken(pAccessToken.getToken());
		serviceBean.setAccessTokenSecret(pAccessToken.getTokenSecret());
		serviceBean.setMemberId(pMemberId);
		// serviceBean.setTwitterId(twitter.getUserId());
		mOAuthService.persistToken(serviceBean); // persist in db for future
		// use.
	}

	@Override
	public List<YouTubeVideo> getYoutubeVideos(Long pMemberId) throws Exception {
		YouTubeService service = getYoutubeService(pMemberId);
		VideoFeed feed = getFeed(service, VideoFeed.class);
		List<VideoEntry> entries = feed.getEntries();
		return GoogleYoutubeUtil.convertToVideos(entries);
	}
}
